/**
 * elancom Corporation copy right 2012 - 2015  
 *   
 * $Header: https://192.168.1.224/svn/elancom/product/elancom-platform/trunk/src/main/java/com/elancom/framework/util/DateTimeUtils.java 1072 2012-07-03 05:58:06Z lanzhouxue $
 * $Id: DateTimeUtils.java 1072 2012-07-03 05:58:06Z lanzhouxue $
 * $Author: lanzhouxue $
 * $Date: 2012-07-03 13:58:06 +0800 (Tue, 03 Jul 2012) $
 * $Revision: 1072 $
 */
package com.elancom.framework.commons.util;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;

/**
 * @author elancom
 * @date Apr 17, 2012
 */
public abstract class DateTimeUtils {
	public final static String DF_DATE = "yyyy-MM-dd";
	public final static String DF_DATETIME = "yyyy-MM-dd HH:mm:ss";
	public final static String DF_TIME = "HH:mm:ss";
	public final static String DF_DATE_CN = "yyyy年MM月dd";
	public final static String DF_DATETIME_CN = "yyyy年MM月dd日 HH:mm:ss";
	public final static String DF_TIME_CN = "HH:ss:mm";
	private static final String YMD = "yyyy-MM-dd";
	private static final String YMD_HMS = "yyyy-MM-dd HH:mm:ss";

	public static String format(Date date, String format) {
		if (date == null) {
			return null;
		}
		final SimpleDateFormat dateFormat = new SimpleDateFormat(format);
		return dateFormat.format(date).toString();
	}

	public static String format(String format) {
		return format(new Date(), format);
	}

	public static String formatDateTime() {
		return formatDateTime(new Date());
	}

	public static String formatDateTime(Date date) {
		return format(date, DF_DATETIME);
	}

	public static Date nextDay(Date date) {
		nextDay(date, 1);
		return date;
	}

	public static Date nextDay(Date date, int days) {
		nextDay(date, days, false);
		return date;
	}

	private static void nextDay(Date date, int days, boolean hold) {
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		c.set(Calendar.AM_PM, Calendar.AM);
		if (!hold) {
			c.set(Calendar.HOUR, 0);
			c.set(Calendar.MINUTE, 0);
			c.set(Calendar.SECOND, 0);
			c.set(Calendar.MILLISECOND, 0);
		}
		c.add(Calendar.DATE, days);
		date.setTime(c.getTimeInMillis());
	}

	public static void main(String[] args) throws ParseException {
		Date date = new Date();
		System.out.println(date);
		nextDay(date, 12);
		System.out.println(date);
		// final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
		// final Date d = dateFormat.parse("2011-08-08");
		// System.out.println(d);
		// System.out.println(format(d, "yyyy-MM-dd HH:mm:ss"));
	}

	public static Date parse(final String date) {
		return parse(date, "yyyy-MM-dd");
	}

	public static Date parse(String str, String format) {
		if (StringUtils.isBlank(str)) {
			return null;
		}
		boolean giveFormat = true;
		if (StringUtils.isBlank(format)) {
			giveFormat = false;
			format = "yyyy-MM-dd";
		}

		try {
			final SimpleDateFormat dateFormat = new SimpleDateFormat(format);
			return dateFormat.parse(str);
		} catch (final ParseException e) {
			if (!giveFormat) {
				final SimpleDateFormat dateFormat = new SimpleDateFormat(format + " HH:mm:ss");
				try {
					return dateFormat.parse(str);
				} catch (final ParseException e1) {
					return null;
				}
			}
		}
		return null;
	}

	public static Date strTimeValue2Date(long longTimeValue) {
		try {
			final Date date = new Date(longTimeValue);
			return date;
		} catch (final Exception e) {
		}
		return null;
	}

	public static Date strTimeValue2Date(String strTimeValue) {
		if (strTimeValue != null && strTimeValue.trim().length() != 0) {
			try {
				final long time = new Long(strTimeValue).longValue();
				final Calendar calendar = Calendar.getInstance();
				calendar.setTimeInMillis(time);
				final Date date = calendar.getTime();
				return date;
			} catch (final Exception e) {
			}
		}
		return null;
	}

	private DateTimeUtils() {
	}

	public <T> Object convert(Class<T> type, Object value) {
		if (value instanceof String) {
			final String p = StringUtils.trim((String) value);
			if (p == null) {
				return null;
			}

			try {
				final SimpleDateFormat df = new SimpleDateFormat(YMD_HMS);
				return df.parse(p.trim());
			} catch (final Exception e) {
				try {
					final SimpleDateFormat df = new SimpleDateFormat(YMD);
					return df.parse(p.trim());
				} catch (final Exception e2) {
					final String dateStr = value.toString();
					try {
						final SimpleDateFormat df = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy", Locale.US);
						return df.parse(dateStr);
					} catch (final ParseException e1) {
						e1.printStackTrace();
					}
					// StringBuffer pPath = new StringBuffer();
					// String year = dateStr.substring(24);
					// String dd = dateStr.substring(8, 10);
					// String mm = dateStr.substring(4, 7);
					// String time = dateStr.substring(11, 19);
					//
					// pPath.append(year).append("-");
					//
					// if (mm.equals("Jan")) {
					// pPath.append("01");
					// } else if (mm.equals("Feb")) {
					// pPath.append("02");
					// } else if (mm.equals("Mar")) {
					// pPath.append("03");
					// } else if (mm.equals("Apr")) {
					// pPath.append("04");
					// } else if (mm.equals("May")) {
					// pPath.append("05");
					// } else if (mm.equals("Jun")) {
					// pPath.append("06");
					// } else if (mm.equals("Jul")) {
					// pPath.append("07");
					// } else if (mm.equals("Aug")) {
					// pPath.append("08");
					// } else if (mm.equals("Sep")) {
					// pPath.append("09");
					// } else if (mm.equals("Oct")) {
					// pPath.append("10");
					// } else if (mm.equals("Nov")) {
					// pPath.append("11");
					// } else if (mm.equals("Dec")) {
					// pPath.append("12");
					// }
					// pPath.append("-").append(dd).append(" ").append(time);
					//
					// SimpleDateFormat df = new SimpleDateFormat(YMD_HMS);
					// try {
					// return df.parse(p.trim());
					// } catch (ParseException e1) {
					// e1.printStackTrace();
					// }

					return null;
				}
			}
		} else {
			if (value instanceof Date) {
				return value;
			}
		}
		return null;
	}

	public static long getTaskTime(Task task) {
		task.prepare();

		final long l1 = System.currentTimeMillis();
		try {
			task.execute();
		} catch (final Exception e) {
			throw new RuntimeException(e);
		}
		final long l2 = System.currentTimeMillis();

		return l2 - l1;
	}

	public static abstract class Task {
		protected void prepare() {
		}

		public abstract void execute() throws Exception;
	}
}
